package io.adrainty.bolee.security.satoken.handler;

import io.adrainty.bolee.framework.commons.basic.ResponseCode;
import io.adrainty.bolee.framework.commons.exception.AppException;
import io.adrainty.bolee.framework.commons.user.UserEntity;
import io.adrainty.bolee.security.models.constants.OAuth2Constants;
import io.adrainty.bolee.security.models.entity.CompanyEntity;
import io.adrainty.bolee.security.models.valobj.GrantTypeEnum;
import io.adrainty.bolee.security.models.valobj.UserTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBucket;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * <p>RefreshTokenGrantTypeHandler</p>
 *
 * @author AdRainty
 * @version V1.0.0
 * @description RefreshTokenGrantTypeHandler
 * @since 2025/8/6 16:26:35
 */

@Slf4j
@Component
public class RefreshTokenGrantTypeHandler extends BaseGrantTypeHandler {

    @Override
    protected UserEntity doGrantHandler(UserTypeEnum userType, Map<String, String> parameters, CompanyEntity companyEntity) {
        String userToken = parameters.get(OAuth2Constants.JTI_KEY);
        String refreshToken = parameters.get(OAuth2Constants.REFRESH_TOKEN_KEY);

        RBucket<String> refreshBucket = redissonClient.getBucket(OAuth2Constants.REFRESH_TOKEN_CACHE + userToken);
        String actualRefreshToken = refreshBucket.get();
        if (StringUtils.isNotBlank(refreshToken) && !actualRefreshToken.equals(refreshToken)) {
            log.error("refreshToken error, accept: {}, actual: {}", refreshToken, actualRefreshToken);
            throw new AppException(ResponseCode.USER_LOGIN_EXPIRED);
        }

        RBucket<UserEntity> userTokenCache = redissonClient.getBucket(OAuth2Constants.USER_TOKEN_CACHE + userToken);
        UserEntity userEntity = userTokenCache.get();
        if (userEntity == null) {
            log.error("userToken expire, userEntity is null");
            throw new AppException(ResponseCode.USER_LOGIN_EXPIRED);
        }

        userEntity.setOnlyAuthenticate(Boolean.TRUE);
        return userEntity;
    }

    @Override
    public String getActualGrantType() {
        return GrantTypeEnum.REFRESH_TOKEN.getCode();
    }

    @Override
    public String getHandlerGrantType() {
        return GrantTypeEnum.REFRESH_TOKEN.getCode();
    }

}
